package org.pisces.wechat.config;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.EnumSet;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.pisces.wechat.enums.EnumIdentifiable;


public  class MyBatisEnumTypeHandler<E extends Enum<E> & EnumIdentifiable<K>,K>  extends BaseTypeHandler<E>{
	
	private Class<E> classType;
	
	public MyBatisEnumTypeHandler(Class<E> classType) {
		this.classType = classType;
	}
	
	public Class<E> getClassType() {
		return classType;
	}
	public void setClassType(Class<E> classType) {
		this.classType = classType;
	}

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, E parameter,
			JdbcType jdbcType) throws SQLException {
		//jdbc type is null
		if(jdbcType == null) {
			K key = parameter.getIdentifiable();
			
			//简单的基础类型设置
			if(key instanceof Integer) {
				ps.setInt(i, (Integer)key);
			}else if(key instanceof String) {
				ps.setString(i, (String)key);
			}else if(key instanceof Boolean ) {
				ps.setBoolean(i, (Boolean)key);
			}else if(key instanceof Long ) {
				ps.setLong(i, (Long)key);
			}else if(key instanceof Double) {
				ps.setDouble(i, (Double)key);
			}else if(key instanceof Short) {
				ps.setShort(i, (Short)key);
			}else{
				throw new RuntimeException("Unknow type of enum");
			}
			
		}else{
			ps.setObject(i, parameter.getIdentifiable(), jdbcType.TYPE_CODE); 
		}
	}

	@Override
	public E getNullableResult(ResultSet rs, String columnName)
			throws SQLException {
		String key = rs.getString(columnName);
		return toEnum(key);
	}

	@Override
	public E getNullableResult(ResultSet rs, int columnIndex)
			throws SQLException {
		String key = rs.getString(columnIndex);
		return toEnum(key);
	}

	@Override
	public E getNullableResult(CallableStatement cs, int columnIndex)
			throws SQLException {
		String key = cs.getString(columnIndex);
		return toEnum(key);
	}

	/**
	 * 转换枚举
	 * @param key
	 * @return
	 */
	private E toEnum(String key) {
		EnumSet<E> enumSet = EnumSet.allOf(this.classType);
		
		if(enumSet == null || enumSet.isEmpty())
			return null;
		for(E e : enumSet){
			if(e==null)continue;
			K k = e.getIdentifiable();
			if(k !=null && k.toString().equalsIgnoreCase(key)) {
				return e;
			}
		}
		return null;
	}
	
}
